﻿using System.Collections.Generic;
using Cms.Application.Admin.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;

namespace Cms.Application.Admin.Presenters
{
    public class CategoriesPresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly ICategoriesView _view;
        
        public CategoriesPresenter(ICategoriesView view)
            : this(view, new RepositoryFactory())
        {
        }

        public CategoriesPresenter(ICategoriesView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!_administrator.HasPermission.Categories)
                _view.RedirectToPermissionDeniedPage();
        }
        
        public void Initialize()
        {
            SetCategories();
        }

        public void SetCategories()
        {
            _view.SetCategories(_administrator.CurrentSite.GetRootCategories());
        }

        public void Delete(int id)
        {
            Category categoryToBeDeleted = PageRepository.GetCategory(id);
            bool hasSameName = false;

            // Check for name collisions between sub items and items at the parent level
            IList<Category> parentLevelItems = categoryToBeDeleted.Parent == null
                                                   ? _administrator.CurrentSite.GetRootCategories()
                                                   : categoryToBeDeleted.Parent.SubCategories;
            foreach (Category parentLevelCategory in parentLevelItems)
            {
                if (parentLevelCategory.ID == categoryToBeDeleted.ID)
                    continue;
                foreach (Category subCategory in categoryToBeDeleted.SubCategories)
                {
                    if (parentLevelCategory.Name.ToLower() == subCategory.Name.ToLower())
                    {
                        AddValidationError(GetText(_view, "DeleteNameCollisionError"));
                        hasSameName = true;
                        break;
                    }
                }
                if (hasSameName)
                    break;
            }
            if (!IsValid)
                return;

            // Move all sub items to the parent item
            foreach (Category subItem in categoryToBeDeleted.SubCategories)
            {
                subItem.Parent = categoryToBeDeleted.Parent;
                if (categoryToBeDeleted.Parent != null)
                    categoryToBeDeleted.Parent.SubCategories.Add(subItem);
            }
            categoryToBeDeleted.SubCategories.Clear();

            // Remove references to the deleted item
            foreach (var content in categoryToBeDeleted.Content)
            {
                content.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.Content.Clear();
            foreach (var folder in categoryToBeDeleted.Folders)
            {
                folder.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.Folders.Clear();
            foreach (var mediaFile in categoryToBeDeleted.MediaFiles)
            {
                mediaFile.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.MediaFiles.Clear();
            foreach(var mediaFolder in categoryToBeDeleted.MediaFolders)
            {
                mediaFolder.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.MediaFolders.Clear();
            foreach (var page in categoryToBeDeleted.Pages)
            {
                page.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.Pages.Clear();
            foreach (var rssFeed in categoryToBeDeleted.RssFeeds)
            {
                rssFeed.Categories.Remove(categoryToBeDeleted);
            }
            categoryToBeDeleted.RssFeeds.Clear();
            categoryToBeDeleted.Site.Categories.Remove(categoryToBeDeleted);
            categoryToBeDeleted.Site = null;
            if (categoryToBeDeleted.Parent != null)
            {
                categoryToBeDeleted.Parent.SubCategories.Remove(categoryToBeDeleted);
                categoryToBeDeleted.Parent = null;
            }
            CategoryRepository.DeleteCategory(categoryToBeDeleted);
            SetCategories();
        }
        
        public void Move(string draggedID, string dropzoneID, string dropzonePart)
        {
            Category targetItem = PageRepository.GetCategory(int.Parse(dropzoneID.Substring(1)));
            Category targetContainer = dropzoneID.Substring(0, 1) == "T" ? targetItem.Parent : targetItem;
            Category movedItem = PageRepository.GetCategory(int.Parse(draggedID.Substring(1)));
            if (movedItem != null && targetItem != null && movedItem.ID != targetItem.ID)
            {
                if (movedItem.IsParentTo(targetItem))
                {
                    AddValidationError(GetText(_view, "IsParentToTargetError"));
                }
                if (!_administrator.CurrentSite.CanCategoryBeNamedAndMovedTo(movedItem.ID, movedItem.Name, movedItem.FolderName, targetContainer))
                {
                    AddValidationError(GetText(_view, "NameCollisionError"));
                }
                if (!IsValid)
                {
                    return;
                }
                if (movedItem.Parent != null)
                {
                    movedItem.Parent.SubCategories.Remove(movedItem);
                }
                if (dropzoneID.Substring(0, 1) == "C")
                {
                    if (targetContainer != null)
                    {
                        targetContainer.SubCategories.Add(movedItem);
                    }
                }
                else 
                {
                    // dropzoneID.Substring(0, 1) == "T"
                    if (dropzonePart == "upper")
                    {
                        if (targetContainer == null)
                        {
                            _administrator.CurrentSite.Categories.Remove(movedItem);
                            _administrator.CurrentSite.Categories.Insert(
                                _administrator.CurrentSite.Categories.IndexOf(targetItem), movedItem);
                        }
                        else
                        {
                            targetContainer.SubCategories.Insert(targetContainer.SubCategories.IndexOf(targetItem), movedItem);
                        }
                    }
                    else 
                    {
                        // dropzonePart == "lower"
                        if (targetContainer == null)
                        {
                            _administrator.CurrentSite.Categories.Remove(movedItem);
                            if (_administrator.CurrentSite.GetRootCategories().IndexOf(targetItem) <
                                _administrator.CurrentSite.GetRootCategories().Count - 1)
                                _administrator.CurrentSite.Categories.Insert(
                                    _administrator.CurrentSite.Categories.IndexOf(targetItem) + 1, movedItem);
                            else
                                _administrator.CurrentSite.Categories.Add(movedItem);
                        }
                        else
                        {
                            if (targetContainer.SubCategories.IndexOf(targetItem) <
                                targetContainer.SubCategories.Count - 1)
                                targetContainer.SubCategories.Insert(
                                    targetContainer.SubCategories.IndexOf(targetItem) + 1, movedItem);
                            else
                                targetContainer.SubCategories.Add(movedItem);
                        }
                    }
                }
                movedItem.Parent = targetContainer;
                SiteRepository.SaveSite(_administrator.CurrentSite);
            }
            SetCategories();
        }
    }
}